<template>
  <div class="file-uploader">
    <div class="uploader-header">
      <h3>上传文件</h3>
      <button class="close-btn" @click="$emit('close')">&times;</button>
    </div>
    
    <div class="uploader-content">
      <div 
        class="dropzone"
        :class="{ active: isDragging }"
        @dragenter="handleDragEnter"
        @dragleave="handleDragLeave"
        @dragover.prevent
        @drop="handleDrop"
        @click="triggerFileInput"
      >
        <input 
          type="file" 
          ref="fileInput" 
          class="file-input" 
          @change="handleFileSelect" 
          :multiple="false"
        />
        <div v-if="!selectedFile" class="dropzone-placeholder">
          <div class="upload-icon">
            <span>📁</span>
          </div>
          <p>拖拽文件到此处或点击选择文件</p>
        </div>
        <div v-else class="selected-file">
          <div class="file-info">
            <div class="file-icon" :class="getFileIconClass(getFileExtension(selectedFile.name))"></div>
            <div class="file-details">
              <div class="file-name">{{ selectedFile.name }}</div>
              <div class="file-size">{{ formatFileSize(selectedFile.size) }}</div>
            </div>
          </div>
          <button class="remove-file-btn" @click.stop="removeFile">移除</button>
        </div>
      </div>
      
      <div v-if="uploadStatus" class="status-container" :class="uploadStatus.type">
        <span class="status-icon">{{ getStatusIcon(uploadStatus.type) }}</span>
        <span class="status-message">{{ uploadStatus.message }}</span>
      </div>
      
      <div v-if="uploadProgress > 0 && uploadProgress < 100" class="progress-container">
        <div class="progress-bar">
          <div class="progress-fill" :style="{ width: uploadProgress + '%' }"></div>
        </div>
        <div class="progress-text">{{ uploadProgress }}%</div>
      </div>
      
      <div class="uploader-actions">
        <button 
          class="cancel-btn" 
          @click="$emit('close')"
          :disabled="isUploading"
        >
          取消
        </button>
        <button 
          class="upload-btn" 
          @click="uploadFile" 
          :disabled="!selectedFile || isUploading"
        >
          {{ isUploading ? '上传中...' : '上传' }}
        </button>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, watch } from 'vue';
import axios from 'axios';
import SparkMD5 from 'spark-md5';

// props和事件
const props = defineProps({
  autoOpenFileDialog: {
    type: Boolean,
    default: false
  },
  initialFile: {
    type: Object,
    default: null
  }
});
const emit = defineEmits(['close', 'upload-success']);

// 状态变量
const fileInput = ref(null);
const selectedFile = ref(null);
const isDragging = ref(false);
const uploadProgress = ref(0);
const isUploading = ref(false);
const uploadStatus = ref(null);

// 监听initialFile变化
watch(() => props.initialFile, (newFile) => {
  if (newFile) {
    selectedFile.value = newFile;
    uploadStatus.value = null;
    uploadProgress.value = 0;
  }
}, { immediate: true });

// 自动打开文件选择对话框
onMounted(() => {
  if (props.autoOpenFileDialog && fileInput.value) {
    setTimeout(() => {
      fileInput.value.click();
    }, 100); // 短暂延迟确保DOM已完全渲染
  }
});

// 文件选择处理
const triggerFileInput = () => {
  if (!isUploading.value) {
    fileInput.value.click();
  }
};

const handleFileSelect = (event) => {
  const file = event.target.files[0];
  if (file) {
    selectedFile.value = file;
    uploadStatus.value = null;
    uploadProgress.value = 0;
  }
};

const removeFile = () => {
  selectedFile.value = null;
  fileInput.value.value = '';
  uploadStatus.value = null;
  uploadProgress.value = 0;
};

// 拖放处理
const handleDragEnter = (e) => {
  e.preventDefault();
  if (!isUploading.value) {
    isDragging.value = true;
  }
};

const handleDragLeave = (e) => {
  e.preventDefault();
  isDragging.value = false;
};

const handleDrop = (e) => {
  e.preventDefault();
  isDragging.value = false;
  
  if (isUploading.value) return;
  
  const file = e.dataTransfer.files[0];
  if (file) {
    selectedFile.value = file;
    uploadStatus.value = null;
    uploadProgress.value = 0;
  }
};

// MD5计算
const calculateMD5 = (file) => {
  return new Promise((resolve, reject) => {
    const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
    const chunkSize = 2097152; // 每次读取2MB
    const chunks = Math.ceil(file.size / chunkSize);
    const spark = new SparkMD5.ArrayBuffer();
    const fileReader = new FileReader();
    let currentChunk = 0;
    
    fileReader.onload = (e) => {
      spark.append(e.target.result);
      currentChunk++;
      
      const progress = Math.round((currentChunk / chunks) * 40); // MD5计算占总进度的40%
      uploadProgress.value = progress;
      
      if (currentChunk < chunks) {
        loadNext();
      } else {
        const md5 = spark.end();
        resolve(md5);
      }
    };
    
    fileReader.onerror = (e) => {
      reject(e);
    };
    
    function loadNext() {
      const start = currentChunk * chunkSize;
      const end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
      fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
    }
    
    loadNext();
  });
};

// 文件上传
const uploadFile = async () => {
  if (!selectedFile.value || isUploading.value) return;
  
  try {
    isUploading.value = true;
    uploadStatus.value = { type: 'info', message: '正在计算文件特征值...' };
    uploadProgress.value = 0;
    
    const token = localStorage.getItem('token');
    const user = localStorage.getItem('user');
    
    if (!token || !user) {
      uploadStatus.value = { type: 'error', message: '用户未登录或登录已过期' };
      isUploading.value = false;
      return;
    }
    
    // 计算文件MD5
    const md5 = await calculateMD5(selectedFile.value);
    
    // 尝试秒传
    uploadStatus.value = { type: 'info', message: '正在检查秒传可行性...' };
    const md5Data = {
      fileName: selectedFile.value.name,
      md5: md5,
      token: token,
      user: user
    };

    const md5CheckResponse = await axios.post('/api/md5', md5Data, {
      headers: {
        'Content-Type': 'application/json'
      }
    });
    
    console.log('MD5检查响应:', md5CheckResponse.data);
    
    // 处理秒传结果
    if (md5CheckResponse.data.code === 0) {
      // 秒传成功
      uploadProgress.value = 100;
      uploadStatus.value = { type: 'success', message: '文件秒传成功！' };
      setTimeout(() => {
        emit('upload-success');
      }, 1500);
      
    } else if (md5CheckResponse.data.code === 5) {
      // 文件已存在
      uploadProgress.value = 100;
      uploadStatus.value = { type: 'warning', message: '该文件已存在！' };
      
    } else if (md5CheckResponse.data.code === 4) {
      // token校验失败
      uploadStatus.value = { type: 'error', message: '登录已过期，请重新登录' };
      setTimeout(() => {
        window.dispatchEvent(new CustomEvent('logout'));
      }, 2000);
      
    } else if (md5CheckResponse.data.code === 1) {
      // 秒传失败，需要实际上传
      uploadStatus.value = { type: 'info', message: '正在上传文件...' };
      
      // 创建FormData对象
      const formData = new FormData();
      formData.append('file', selectedFile.value);
      formData.append('user', user);
      formData.append('md5', md5);
      formData.append('size', selectedFile.value.size);
      // formData.append('token', token);
      
      // 发起上传请求
      const uploadResponse = await axios.post('/api/upload', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        },
        onUploadProgress: (progressEvent) => {
          // 上传进度从40%到100%
          const percentCompleted = Math.round(
            (progressEvent.loaded * 60 / progressEvent.total) + 40
          );
          uploadProgress.value = percentCompleted;
        }
      });
      
      console.log('文件上传响应:', uploadResponse.data);
      
      if (uploadResponse.data.code === 0) {
        uploadStatus.value = { type: 'success', message: '文件上传成功！' };
        setTimeout(() => {
          emit('upload-success');
        }, 1500);
      } else {
        uploadStatus.value = { type: 'error', message: uploadResponse.data.message || '上传失败' };
      }
    } else {
      // 其他错误
      uploadStatus.value = { type: 'error', message: '上传失败，请稍后重试' };
    }
    
  } catch (error) {
    console.error('文件上传错误:', error);
    uploadStatus.value = { type: 'error', message: '上传过程中发生错误' };
  } finally {
    isUploading.value = false;
  }
};

// 辅助函数
const getFileExtension = (filename) => {
  return filename.slice((filename.lastIndexOf('.') - 1 >>> 0) + 2).toLowerCase();
};

const getFileIconClass = (fileType) => {
  const typeMap = {
    'png': 'image-icon',
    'jpg': 'image-icon',
    'jpeg': 'image-icon',
    'gif': 'image-icon',
    'mp4': 'video-icon',
    'avi': 'video-icon',
    'mov': 'video-icon',
    'pdf': 'pdf-icon',
    'doc': 'doc-icon',
    'docx': 'doc-icon',
    'xls': 'excel-icon',
    'xlsx': 'excel-icon',
    'txt': 'text-icon',
    'zip': 'archive-icon',
    'rar': 'archive-icon',
    'dll': 'binary-icon'
  };
  
  return typeMap[fileType] || 'file-icon';
};

const formatFileSize = (bytes) => {
  if (bytes === 0) return '0 B';
  
  const k = 1024;
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};

const getStatusIcon = (type) => {
  const icons = {
    'info': 'ℹ️',
    'success': '✅',
    'error': '❌',
    'warning': '⚠️'
  };
  
  return icons[type] || 'ℹ️';
};
</script>

<style scoped>
.file-uploader {
  background-color: white;
  border-radius: 8px;
  width: 500px;
  max-width: 95%;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  overflow: hidden;
}

.uploader-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 15px 20px;
  background-color: #f5f5f5;
  border-bottom: 1px solid #eee;
}

.uploader-header h3 {
  margin: 0;
  font-size: 18px;
  color: #333;
}

.close-btn {
  background: none;
  border: none;
  font-size: 24px;
  cursor: pointer;
  color: #666;
  padding: 0;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
}

.close-btn:hover {
  background-color: #e0e0e0;
}

.uploader-content {
  padding: 20px;
}

.dropzone {
  border: 2px dashed #ccc;
  border-radius: 6px;
  padding: 30px;
  text-align: center;
  cursor: pointer;
  transition: all 0.2s;
  position: relative;
  margin-bottom: 15px;
}

.dropzone.active {
  border-color: #1e88e5;
  background-color: #e3f2fd;
}

.file-input {
  display: none;
}

.dropzone-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.upload-icon {
  font-size: 32px;
  margin-bottom: 10px;
  color: #757575;
}

.dropzone p {
  margin: 0;
  color: #757575;
}

.selected-file {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.file-info {
  display: flex;
  align-items: center;
  gap: 10px;
}

.file-icon {
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  color: white;
  font-size: 20px;
}

.file-details {
  text-align: left;
}

.file-name {
  font-weight: 500;
  margin-bottom: 5px;
  color: #333;
  word-break: break-word;
}

.file-size {
  font-size: 12px;
  color: #757575;
}

.remove-file-btn {
  background: none;
  border: 1px solid #ddd;
  padding: 5px 10px;
  border-radius: 4px;
  cursor: pointer;
  color: #666;
}

.remove-file-btn:hover {
  background-color: #f5f5f5;
}

.status-container {
  margin: 15px 0;
  padding: 10px 15px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.status-container.info {
  background-color: #e3f2fd;
  border-left: 4px solid #1e88e5;
}

.status-container.success {
  background-color: #e8f5e9;
  border-left: 4px solid #4caf50;
}

.status-container.error {
  background-color: #ffebee;
  border-left: 4px solid #f44336;
}

.status-container.warning {
  background-color: #fff8e1;
  border-left: 4px solid #ffb300;
}

.status-icon {
  font-size: 16px;
}

.status-message {
  flex: 1;
  color: #333;
}

.progress-container {
  margin: 15px 0;
}

.progress-bar {
  height: 8px;
  background-color: #e0e0e0;
  border-radius: 4px;
  overflow: hidden;
  margin-bottom: 5px;
}

.progress-fill {
  height: 100%;
  background-color: #1e88e5;
  transition: width 0.3s;
}

.progress-text {
  text-align: right;
  font-size: 12px;
  color: #757575;
}

.uploader-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 20px;
}

.cancel-btn {
  background-color: #f5f5f5;
  color: #333;
}

.upload-btn {
  background-color: #1e88e5;
}

.upload-btn:disabled {
  background-color: #bbdefb;
  cursor: not-allowed;
}

/* 文件图标样式 */
.image-icon { background-color: #81c784; }
.video-icon { background-color: #64b5f6; }
.pdf-icon { background-color: #e57373; }
.doc-icon { background-color: #4fc3f7; }
.excel-icon { background-color: #66bb6a; }
.text-icon { background-color: #9e9e9e; }
.archive-icon { background-color: #ffb74d; }
.binary-icon { background-color: #ba68c8; }
.file-icon { background-color: #9e9e9e; }
</style> 